import { isObject } from 'lodash'
import useUserInfo from '@/store/useUserInfo'
import Axios, { AxiosRequestConfig, AxiosResponse } from 'axios'
import router from '@/router/index'
import i18n from '@/i18n'
import { useLoadingBar, useNotification, useMessage } from '@/main'
import { useEnv } from '@/store/useEnv'
import { watch } from 'vue'

export const useApi = (() => {
  let reqNums = 0
  const htmlEl = document.querySelector('html') as HTMLHtmlElement
  const interceptRequest = (config: AxiosRequestConfig) => {
    const token = useUserInfo().token
    if (token) config!.headers!.token = token
    if (config.loading !== false) {
      reqNums++
      useLoadingBar().start()
      htmlEl.classList.add('cursor-wait', 'pointer-events-none')
    }
    return config
  }
  const throwErr = ({ config, message }) => {
    let isCancel = false
    try {
      if (!config && isObject(JSON.parse(message))) isCancel = true
    } catch (err) {
      //
    }
    if (isCancel) config = JSON.parse(message)
    if (config.loading !== false) reqNums && reqNums--
    if (!reqNums) {
      useLoadingBar().error()
      htmlEl.classList.remove('cursor-wait', 'pointer-events-none')
    }
    if (isCancel) throw new Error('取消请求')
    message = message?.code || message
    // @ts-ignore
    const title = i18n.global.t('request-error')
    if (config?.data?.code === 401 && !useUserInfo().token) return
    useNotification().error({ title, content: message })
    throw new Error(message)
  }
  const interceptResponse = (config: AxiosResponse) => {
    if (config.status !== 200) return throwErr({ config, message: config.statusText })
    if (config.data?.code === 401) {
      useUserInfo().$patch({ token: '' })
      router.push('/login')
    }
    if (config.data?.type === 'error') return throwErr({ config, message: config.data.msg })
    if (config.data?.type === 'success') useMessage().success(config.data.msg)
    if (config.data?.type === 'warning') {
      const title = i18n.global.t('request-abnormal')
      useNotification().warning({
        title,
        content: config.data.msg
      })
    }
    if (config.config.loading !== false) reqNums--
    if (!reqNums) {
      useLoadingBar().finish()
      htmlEl.classList.remove('cursor-wait', 'pointer-events-none')
    }
    return config.retainCode ? config.data : config.data.data
  }

  return () => {
    const env = useEnv()
    const options: AxiosRequestConfig = { baseURL: env.apiUrl }
    const api = Axios.create(options)
    watch(
      () => env.isIpv6,
      () => {
        api.defaults.baseURL = env.apiUrl
      }
    )
    api.interceptors.request.use(interceptRequest)
    api.interceptors.response.use(interceptResponse, throwErr)
    return api
  }
})()
